const router = require('koa-router')();
const DB = require('../db');
const md5 = require('blueimp-md5');
const jwt = require('jsonwebtoken');
const { SECRETKEY, expiresIn } = require('../token.config');
const generateUid = require('../utils/generateUid');

// router.prefix('/api');

router.get('/', async (ctx, next) => {
  ctx.body = 'hello koa2'
})

/**注册 */
router.post('/register', async (ctx, next) => {

  const body = ctx.request.body;
  const { userName, password, sex, headImg } = body;

  if (!userName || !password || (!sex && sex !== 0) || !headImg) {

    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: false
    }

    return;
  }

  let r = [];
  // 注册的用户名不能和别的用户名重复，也不能和已有的uid重复
  if (isNaN(userName)) {
    r = await DB.find('users', { userName });
  } else {
    r = await DB.find('users', { $or: [{userName}, {uid: parseInt(userName)}] });
  }

  if (r.length > 0) {

    ctx.body = {
      code: "0006",
      message: '账号被占用',
      data: false
    }
  } else {
    // 设置token
    const token = jwt.sign({ userName, password }, SECRETKEY, { expiresIn });

    const datas = {
      userName, // 账号
      nick: '', // 昵称
      password: md5(password), // 密码
      uid: generateUid(Date.now()), // 用户的uid
      avatarUrl: headImg, // 用户头像地址
      token, // token
      registerDate: Date.now(), // 注册时间
      lastLoginDate: Date.now(), // 上次登录时间
      allTasksNumbersSinceRegister: 0, // 从注册到当前时间创建任务总数
      doneTasksNumbersSinceRegister: 0, // 从注册到当前时间完成任务总数
      sex, // 性别 0女 1男 2保密
      birthDay: [2022, 6, 8], // 生日 年月日
      allTasks: [], // 全部任务 isDone为true 已完成， 为false 表示未完成
      totalRecharge: 0, // 总充值数
      rechargeRecord: [], // 充值记录
      totalConsume: 0,
      consumeDetails: [], // 消费明细
      gMoney: 0, // 当前G币余额
      totalAnswerNumbers: 0, // 总答题数
      acceptionNumbers: 0, // 答题被采纳数
      gMoneyFromAnswers: 0, // 答题所赚G币数
    };

    // 向users文档添加对象数据
    await DB.add('users', datas);

    // 设置cookie，缓存数据
    ctx.cookies.set('userName', userName, {
      maxAge: expiresIn * 1000, // 有效期，ms ，这里要和token有效期保持一致
    })

    ctx.body = {
      code: "0000",
      message: '注册成功',
      data: {
        userName,
        token,
        nick: datas.nick,
        uid: datas.uid,
        avatarUrl: headImg,
        sex
      }
    }
  }
})

/**登录 */
router.post('/login', async (ctx, next) => {

  const body = ctx.request.body;
  const { userName, password } = body;

  const r1 = await DB.find('users', { userName, password: md5(password) });

  if (!r1 || r1.length === 0) {

    ctx.body = {
      code: '0007',
      message: '账号或密码错误',
      data: false
    }

    return;
  }

  // 签发token
  const token = jwt.sign({ userName, password }, SECRETKEY, { expiresIn })

  const { nick, uid, avatarUrl, sex } = r1[0];

  ctx.body = {
    code: "0000",
    message: '登录成功',
    data: {
      userName,
      token,
      nick,
      uid,
      avatarUrl,
      sex
    }
  }

  // 更新最近一次登录时间和token
  await DB.updateValue('users', { userName }, { lastLoginDate: Date.now(), token });

  // 设置cookie，缓存数据
  ctx.cookies.set('userName', userName, {
    maxAge: expiresIn * 1000, // 有效期，ms ，这里要和token有效期保持一致
  })
})

/**获取登录信息 */
router.get('/getUserInfo', async (ctx, next) => {
  const { userName, passward } = ctx.query;
  const r = await DB.find('users', { userName, passward: md5(passward) });
  if (!r || r.length === 0) {
    ctx.body = {
      code: '0007',
      message: '账号或密码错误',
      data: {}
    }
    return;
  }
  if (!ctx.cookies.get('userName')) {
    ctx.body = {
      code: '0008',
      message: '登录信息已过期',
      data: {}
    }
    return;
  }
  ctx.body = {
    code: '0000',
    message: '获取登录信息成功',
    data: {
      userName: r[0].userName,
      token: r[0].token
    }
  }
})

/**退出登录 */
router.post('/logout', async (ctx, next) => {

  const userName = ctx.request.header.username;

  await DB.updateValue('users', { userName }, { token: '' });

  ctx.body = {
    code: '0000',
    message: '退出成功',
    data: true
  }
})

/**创建任务 */
router.post('/createtask', async (ctx, next) => {

  const body = ctx.request.body;
  const { title, content, taskDate } = body;
  const preDate = body.preDate ? new Date(body.preDate) + (24 * 60 * 60 - 1) * 1000 : 0;

  if (!title || !content || !taskDate) {

    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: []
    }

    return;
  }

  const userName = ctx.request.header.username;

  if (!userName) {

    // ctx.body = {
    //   code: '0012',
    //   message: '缺少请求头参数',
    //   data: false
    // }

    ctx.redirect('/login');

    return;
  }

  const r = await DB.find('users', { userName });

  if (r.length === 0) {

    ctx.body = {
      code: '0013',
      message: '未查询到指定内容',
      data: []
    }

    return;
  }

  const atr = r[0].allTasksNumbersSinceRegister;

  // 更新创建任务总数
  await DB.updateValue('users', { userName }, { allTasksNumbersSinceRegister: atr + 1 });

  const newData = {
    dayId: taskDate,
    taskId: taskDate + '_' + Date.now(),
    title,
    content,
    preDate,
    createTime: Date.now(),
    isDone: false,
    doneTime: 0 // 完成时间 时间戳
  };

  await DB.updateDeep('users', { userName }, { allTasks: newData });

  ctx.body = {
    code: '0000',
    message: '创建成功！',
    data: [newData]
  }
})

// 获取指定日期任务列表
router.get('/theDayTaskList', async (ctx, next) => {

  const { taskDate } = ctx.query;
  const userName = ctx.request.header.username;

  if (!taskDate) {

    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: []
    }

    return;
  }

  const r1 = await DB.findDayIdInAllTasks('users', userName, taskDate);

  const list = r1.length ? r1[0].allTasks.filter(item => item.dayId === taskDate) : [];

  // 排序规则：先创建的未完成任务放在前面
  const notDoneList = list.filter(item => !item.isDone).sort((a, b) => b.createTime - a.createTime);

  const doneList = list.filter(item => item.isDone); // 已完成的任务就不设置排序规则了

  const result = [...notDoneList, ...doneList];


  ctx.body = {
    code: '0000',
    message: '获取成功',
    data: result
  }
})

// 设为已完成
router.post('/setDone', async (ctx, next) => {

  const { taskId } = ctx.request.body;
  const userName = ctx.request.header.username;

  if (!taskId) {
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: []
    }

    return;
  }

  await DB.setTaskDone('users', userName, taskId);

  const r = await DB.find('users', { userName });

  const allTasks = r[0].allTasks.filter(item => item.dayId === taskId.split('_')[0]);

  const task = [...allTasks.filter(item => !item.isDone).sort((a, b) => b.createTime - a.createTime), ...allTasks.filter(item => item.isDone)];

  ctx.body = {
    code: '0000',
    message: '设置成功',
    data: task
  }
})

// 删除一条任务
router.post('/delOneTask', async (ctx, next) => {

  const { taskId } = ctx.request.body;
  const userName = ctx.request.header.username;

  if (!taskId) {
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: []
    }

    return;
  }

  const r = await DB.find('users', { userName });

  await DB.delOneTask('users', userName, taskId);

  const del = r[0].allTasks.filter(item => item.taskId === taskId);

  ctx.body = {
    code: '0000',
    message: '删除成功',
    data: del
  }
})

// 清除指定日期所有任务
router.post('/clearAllTasks', async (ctx, next) => {

  const { dayId } = ctx.request.body;
  const userName = ctx.request.header.username;

  if (!dayId) {
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: []
    }

    return;
  }

  await DB.clearAllTasks('users', userName, dayId);

  ctx.body = {
    code: '0000',
    message: '任务已清空',
    data: []
  }
})

// 获取未完成指示牌数据
router.get('/notDoneList', async (ctx, next) => {

  const userName = ctx.request.header.username;

  const r = await DB.find('users', { userName });

  const allTasks = r[0].allTasks.filter(item => !item.isDone);

  const obj = {};

  allTasks.forEach(item => {
    
    if (Object.keys(obj).includes('a' + item.dayId)) {
      
      obj['a' + item.dayId]++;
    } else {

      obj['a' + item.dayId] = 1;
    }
  })

  const arr = [];

  for (let k in obj) {
    arr.push([k.slice(1), obj[k]]);
  }

  ctx.body = {
    code: '0000',
    message: '指示牌数据',
    data: arr
  }
})

// 获取当月每日未完成数据
router.get('/everyDayAMonth', async (ctx, next) => {

  const { y, m } = ctx.query;
  const userName = ctx.request.header.username;

  if (!y || !m) {
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: {}
    }

    return;
  }

  const r = await DB.find('users', { userName });

  const allTasks = r[0].allTasks.filter(item => !item.isDone && item.dayId.includes(y + '-' + m));

  const obj = {};

  allTasks.forEach(item => {
    
    if (Object.keys(obj).includes('a' + item.dayId)) {
      
      obj['a' + item.dayId]++;
    } else {

      obj['a' + item.dayId] = 1;
    }
  })

  ctx.body = {
    code: '0000',
    message: '获取成功',
    data: obj
  }
})

// 获取自定义节日列表
router.get('/getAllFestival', async (ctx, next) => {

  const userName = ctx.request.header.username;

  const r = await DB.find('users', { userName });

  ctx.body = {
    code: '0000',
    message: '获取成功',
    data: r[0].customizeFestival || []
  }
})

// 添加自定义节日
router.post('/addFestival', async (ctx, next) => {

  const { m, d, content, isRemind } = ctx.request.body;
  const userName = ctx.request.header.username;

  if (!m || !d || !content || typeof isRemind !== 'boolean') {
    
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: {}
    }

    return;
  }

  const r = await DB.find('users', { userName });
  const customizeFestival = r[0].customizeFestival;
  const addData = {
    m,
    d,
    content,
    isRemind,
    createTime: Date.now()
  };

  customizeFestival
    ? await DB.updateDeep('users', { userName }, { customizeFestival: addData })
    : await DB.updateValue('users', { userName }, { customizeFestival: [addData] });

  ctx.body = {
    code: '0000',
    message: '添加成功',
    data: addData
  };
})

// 重新编辑某个节日
router.post('/reEditFestival', async (ctx, next) => {

  const { createTime, m, d, content, isRemind } = ctx.request.body;
  const userName = ctx.request.header.username;

  if (!createTime || !m || !d || !content || typeof isRemind !== 'boolean') {
    
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: 0
    }

    return;
  }

  const r = await DB.find('users', { userName });
  const reData = {
    m,
    d,
    content,
    isRemind,
    createTime: Date.now()
  };

  await DB.modifyFestival('users', userName, createTime, reData);

  ctx.body = {
    code: '0000',
    message: '更新成功',
    data: {
      reData,
      createTime
    }
  }

})

// 删除某个自定义节日
router.post('/removeOneFestival', async (ctx, next) => {

  const { createTime } = ctx.request.body;
  const userName = ctx.request.header.username;

  if (!createTime) {
    
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: 0
    }

    return;
  }

  await DB.removeOneFestival('users', userName, createTime);

  ctx.body = {
    code: '0000',
    message: '删除成功',
    data: createTime
  }
})

// 获取某个自定义节日
router.get('/queryOneFestival', async (ctx, next) => {

  const { createTime } = ctx.query;
  const userName = ctx.request.header.username;

  if (!createTime) {
    
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: {}
    }

    return;
  }

  const r = await DB.find('users', { userName });
  const queryData = r[0].customizeFestival.find(item => item.createTime === parseInt(createTime));

  ctx.body = {
    code: '0000',
    message: '获取成功',
    data: queryData
  };
})

// 清除全部自定义节日
router.post('/clearAllFestival', async (ctx, next) => {

  const userName = ctx.request.header.username;

  await DB.updateValue('users', { userName }, { customizeFestival: [] });

  ctx.body = {
    code: '0000',
    message: '清除成功',
    data: []
  }
})

// 获取当前注册用户数量
router.get('/totalUserNumbers', async (ctx, next) => {

  const r0 = await DB.findAll('users');

  ctx.body = {
    code: '0000',
    message: '获取成功',
    data: r0.length
  }
})

/********************************************************************** 
 * ********************************************************************* 
 * ********************************************************************* 
 * ********************************************************************* 
 * ********************************************************************* 
 * ********************************************************************* 
 * ********************************************************************* 
 * ********************************************************************* 
*/

/**
 * 获取任务列表 
 * @type 0 进行中
 * @type 1 已完成
 */

router.get('/taskLists', async (ctx, next) => {
  const { type } = ctx.query
  if (!type) {
    ctx.body = {
      code: '0002',
      message: '缺少type参数',
      data: false
    }
    return
  }
  if (type !== '0' && type !== '1') {
    ctx.body = {
      code: '0003',
      message: '未按指定要求传参',
      data: false
    }
    return
  }
  const userName = ctx.request.header.username
  const r = await DB.find('users', { userName })
  if (r.length === 0) {
    ctx.body = {
      code: '0013',
      message: '未查询到指定内容',
      data: false
    }
    return
  }
  ctx.body = {
    code: '0000',
    message: 'success',
    data: type === '0' ? r[0].goingTasks : r[0].doneTasks
  }
})

/**删除一条任务 */
router.post('/delOne', async (ctx, next) => {
  const { type, dataId } = ctx.request.body
  const userName = ctx.request.header.username
  const r = await DB.find('users', { userName })
  if (r.length === 0) {
    ctx.body = {
      code: '0013',
      message: '未查询到指定内容',
      data: false
    }
    return
  }
  const arrName = parseInt(type) === 0 ? 'goingTasks' : 'doneTasks'
  await DB.updataDelInArr('users', { userName }, { [arrName]: { id: dataId } })
  ctx.body = {
    code: '0000',
    message: '删除成功',
    data: true
  }
})

/**将一个未完成设置为已完成 */
router.post('/toDone', async (ctx, next) => {
  const { dataId } = ctx.request.body
  const userName = ctx.request.header.username
  const r = await DB.find('users', { userName })
  if (r.length === 0) {
    ctx.body = {
      code: '0013',
      message: '未查询到指定内容',
      data: false
    }
    return
  }
  const { id, title, content, createDate } = r[0].goingTasks.find(item => item.id === dataId)
  await DB.updataDelInArr('users', { userName }, { goingTasks: { id: dataId } })
  await DB.updateDeep('users', { userName }, {
    doneTasks: {
      id,
      title,
      content,
      createDate,
      doneDate: Date.now(),
      consumeHours: ((Date.now() - createDate) / 1000 / 60 / 60).toFixed(2)
    }
  })
  await DB.updateValue('users', { userName }, { doneTasksNumbersSinceRegister: r[0].doneTasksNumbersSinceRegister + 1})
  ctx.body = {
    code: '0000',
    message: '设置成功',
    data: true
  }
})

/**退出登录 */
router.post('/exitLogin', async (ctx, next) => {
  const userName = ctx.request.header.username
  const r = await DB.find('users', { userName })
  if (r.length === 0) {
    ctx.body = {
      code: '0013',
      message: '未查询到指定内容',
      data: false
    }
    return
  }
  await DB.updateValue('users', { userName }, { token: '' })
  ctx.cookies.set('userName', '', { maxAge: 0 })
  ctx.body = {
    code: '0000',
    message: '退出成功',
    data: true
  }
  ctx.redirect('/')
})

/**充值 */
router.post('/recharge', async (ctx, next) => {
  const { _username, money, paymentChannel } = ctx.request.body
  if (!_username || !money || !paymentChannel) {
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: false
    }
    return
  }
  if (typeof money !== 'number') {
    ctx.body = {
      code: '0001',
      message: '传入参数数据类型不正确',
      data: false
    }
    return
  }
  const r = await DB.find('users', { userName: _username })
  if (r.length === 0) {
    ctx.body = {
      code: '0013',
      message: '充值用户不存在',
      data: false
    }
    return
  }
  const t = r[0].totalRecharge
  const g = r[0].gMoney
  await DB.updateValue('users', { userName: _username }, {
    totalRecharge: t + money,
    gMoney: g + money
  })
  await DB.updateDeep('users', { userName: _username }, {
    rechargeRecord: {
      rechargeDate: Date.now(), // 充值日期
      orderId: 'T' + Date.now(), // 订单号
      payAmount: money, // 充值金额
      receiveGmoney: money, // 到账G币
      paymentChannel, // 支付渠道 如 支付宝 微信
      paymentStatus: '已支付', // 支付状态 如未支付 已支付
    }
  })
  ctx.body = {
    code: '0000',
    message: '充值成功',
    data: true
  }
})

/**获取当前G币余额 */
router.get('/gmoney', async (ctx, next) => {
  const userName = ctx.request.header.username
  const r = await DB.find('users', { userName })
  if (r.length === 0) {
    ctx.body = {
      code: '0013',
      message: '未查询到指定内容',
      data: false
    }
    return
  }
  ctx.body = {
    code: '0000',
    message: '获取成功',
    data: r[0].gMoney
  }
})

/**
 * 获取充值记录/消费明细
 * @currentPage 当前页 从1开始
 * @type 1-获取充值记录 2-获取消费明细
 * @numbersOnePage 一页有多少条
 */
router.get('/rechargeConsume', async (ctx, next) => {
  const userName = ctx.request.header.username
  let { currentPage, type, numbersOnePage } = ctx.query
  if (!currentPage || !type || !numbersOnePage) {
    ctx.body = {
      code: '0002',
      message: '缺少必要参数',
      data: false
    }
    return
  }
  if (isNaN(Number(currentPage)) || isNaN(Number(type)) || isNaN(Number(numbersOnePage))) {
    ctx.body = {
      code: '0001',
      message: '传入参数数据类型不正确',
      data: false
    }
    return
  }
  currentPage = Number(currentPage)
  type = Number(type)
  numbersOnePage = Number(numbersOnePage)
  if (type !== 1 && type !== 2) {
    ctx.body = {
      code: '0003',
      message: '未按指定要求传参',
      data: false
    }
    return
  }
  const r = await DB.find('users', { userName })
  if (r.length === 0) {
    ctx.body = {
      code: '0013',
      message: '未查询到指定内容',
      data: false
    }
    return
  }
  if (type === 1) {
    ctx.body = {
      code: '0000',
      message: '获取成功',
      data: {
        onePage: r[0].rechargeRecord.slice((currentPage - 1) * numbersOnePage, currentPage * numbersOnePage),
        rechargeRecord: r[0].rechargeRecord
      }
    }
  } else if (type === 2) {
    ctx.body = {
      code: '0000',
      message: '获取成功',
      data: {
        onePage: r[0].consumeDetails.slice((currentPage - 1) * numbersOnePage, currentPage * numbersOnePage),
        consumeDetails: r[0].consumeDetails
      }
    }
  }
})

/**答题榜
 * @type 1-按答题数 2-按被采纳数 3-按赚G币数量
 */
router.get('/answerRank', async (ctx, next) => {
  const { type } = ctx.query
  if (!type) {
    ctx.body = {
      code: '0002',
      message: '缺少榜单类型参数type',
      data: false
    }
    return
  }
  if (type === '1') {
    const r = await DB.findInSort('users', 'totalAnswerNumbers', 0)
    const arr = r.map((item, index) => ({
      sort: index + 1, // 排名
      nick: item.nick, // 昵称
      totalAnswerNumbers: item.totalAnswerNumbers, // 总回答数
      acceptionNumbers: item.acceptionNumbers, // 被采纳数
      gMoneyFromAnswers: item.gMoneyFromAnswers // 赢得的G币数
    }))
    ctx.body = {
      code: '0000',
      message: '获取成功',
      data: arr
    }
  } else if (type === '2') {
    const r = await DB.findInSort('users', 'acceptionNumbers', 0)
    const arr = r.map((item, index) => ({
      sort: index + 1,
      nick: item.nick,
      totalAnswerNumbers: item.totalAnswerNumbers,
      acceptionNumbers: item.acceptionNumbers,
      gMoneyFromAnswers: item.gMoneyFromAnswers
    }))
    ctx.body = {
      code: '0000',
      message: '获取成功',
      data: arr
    }
  } else if (type === '3') {
    const r = await DB.findInSort('users', 'gMoneyFromAnswers', 0)
    const arr = r.map((item, index) => ({
      sort: index + 1,
      nick: item.nick,
      totalAnswerNumbers: item.totalAnswerNumbers,
      acceptionNumbers: item.acceptionNumbers,
      gMoneyFromAnswers: item.gMoneyFromAnswers
    }))
    ctx.body = {
      code: '0000',
      message: '获取成功',
      data: arr
    }
  } else {
    ctx.body = {
      code: '0001',
      message: '榜单类型参数type不符合指定要求',
      data: false
    }
  }
})

module.exports = router